package com.example.crawlerjava.service.upload.impl;

import cn.hutool.core.util.ObjectUtil;
import com.example.crawlerjava.config.CrawlerConfig;
import com.example.crawlerjava.config.WormholeConfig;
import com.example.crawlerjava.constant.CacheKey;
import com.example.crawlerjava.entity.UploadEntity;
import com.example.crawlerjava.service.upload.UploadStrategy;
import com.example.crawlerjava.util.CaffeineUtil;
import com.microsoft.playwright.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.stereotype.Service;

import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service("wormholeUpload")
public class WormholeUploadImpl implements UploadStrategy {

    @Resource
    private WormholeConfig wormholeConfig;
    @Resource
    private CrawlerConfig crawlerConfig;

    @Resource
    private CaffeineCacheManager cacheManager;

    @Override
    public void upload(String uploadFilePath, String queryId) {
        UploadEntity uploadEntity = new UploadEntity();
        try (Playwright playwright = Playwright.create()) {
            String baseUrl = wormholeConfig.getWormholeUrl();
            BrowserType chromium = playwright.chromium();
            Path userDataDir = Paths.get(wormholeConfig.getWormholePlaywright());
            BrowserType.LaunchPersistentContextOptions options = new BrowserType.LaunchPersistentContextOptions();
            //这里代表是否要可视化，false代表可视化，true代表非可视化
            if (crawlerConfig.getOpenView()) {
                options.setHeadless(false);
                options.setViewportSize(1920, 1080);
            } else {
                options.setHeadless(true);
            }
            options.setAcceptDownloads(true)
                    .setJavaScriptEnabled(true)
                    .setBypassCSP(true);

            BrowserContext browserContext = chromium.launchPersistentContext(userDataDir, options);
            browserContext.setDefaultTimeout(300000);

            URL url = this.getClass().getResource("/" + "stealth.min.js");
            Path filePath = Paths.get(url.toURI());
            browserContext.addInitScript(filePath);
            Page page = browserContext.newPage();
            page.navigate(baseUrl);

            Path uploadFile = Paths.get(uploadFilePath);
            page.setInputFiles("input[type='file']", uploadFile);

            // 等待指定元素出现
            page.waitForSelector("input.chakra-input.css-o1yeot", new Page.WaitForSelectorOptions()
                    .setTimeout(30000)); // 设置超时时间为 30 秒

            // 获取 input 元素的 value 属性
            Object o = page.locator("input.chakra-input.css-o1yeot")
                    .evaluateHandle("el => el.value")
                    .jsonValue();
            String inputValue = o.toString();

            uploadEntity.setDownloadUrl(inputValue);
            uploadEntity.setUploadResult(false);

            cacheManager.getCache(CacheKey.DOWNLOAD_KEY).put(queryId, uploadEntity);
            Cache cache = cacheManager.getCache(CacheKey.DOWNLOAD_KEY);
            UploadEntity upload = CaffeineUtil.getValue(queryId, cache, UploadEntity.class);
            log.info("查询的key{},上传结果:{}", queryId, upload);

            // 等待包含“已上传”的元素出现
            int loopCount = 0;

            while (true) {
                String selector = ".chakra-offset-slide .chakra-stack .chakra-heading";
                Page.WaitForSelectorOptions selectorOptions = new Page.WaitForSelectorOptions();
                selectorOptions.setTimeout(30000);
                List<ElementHandle> elementHandles = page.querySelectorAll(selector);
                boolean endFlag = false;
                for (ElementHandle handle : elementHandles) {
                    String text = handle.textContent();
                    log.info("当前文本为:{}", text);
                    //这里主要取决于网站选择器的对应文本
                    if (Objects.equals(text, "已上传") || Objects.equals(text, "Uploaded")) {
                        endFlag = true;
                        uploadEntity.setUploadResult(true);
                        break;
                    }
                }
                if (endFlag || loopCount > 2000) {
                    break;
                }
                log.info("等待中...,循环次数为{}", loopCount);
                Thread.sleep(2000);
                loopCount++;
            }
            log.info("上传成功:{}", uploadFilePath);
            // 输出 value
            uploadEntity.setDownloadUrl(inputValue);
            uploadEntity.setUploadResult(true);
            cacheManager.getCache(CacheKey.DOWNLOAD_KEY).put(queryId, uploadEntity);
        } catch (Exception e) {
            log.error("上传失败:{}", uploadFilePath, e);
            uploadEntity.setUploadResult(false);
        }
    }

    @Override
    public UploadEntity getUploadResult(String queryKey) {
        if (ObjectUtil.isEmpty(queryKey)) {
            return null;
        }
        //从缓存获取数据
        Cache cache = cacheManager.getCache(CacheKey.DOWNLOAD_KEY);
        return CaffeineUtil.getValue(queryKey, cache, UploadEntity.class);
    }
}
